
#include "mb_slave.h"
#include "mb_adu.h"
#include "mb_coils.h"
#include "mb_crc.h"
#include "mb_datamodel.h"
#include "mb_debug.h"
#include "mb_discreteinputs.h"
#include "mb_functioncode.h"
#include "mb_holdingregisters.h"
#include "mb_inputregisters.h"

/**
 * @brief 从站协议解析出错
 * @param hslave          从站指针
 * @param ExceptionCode   错误功能码
 * @param pDst            回复数据
 * @param pDstLen         回复数据长度
 * @ret   MB_OK  正确, MB_ERROR 失败
*/
MB_StatusTypeDef MB_SLAVE_ExceptionRsp(MB_SLAVE_HandleTypeDef *hslave, uint8_t FunctionCode, uint8_t ExceptionCode, uint8_t *pDst, uint16_t *pDstLen)
{
    uint16_t crc;
    MB_ExceptionADU_HandleTypeDef *pDspAdu = (MB_ExceptionADU_HandleTypeDef *)pDst;
    pDspAdu->AdditionalAddress = hslave->SlaveID;
    pDspAdu->Pdu.FunctionCode = FunctionCode | 0x80;
    pDspAdu->Pdu.ExceptionCode = ExceptionCode;
    crc = MB_GenerateCRC16CheckCode(pDst, 3);
    pDspAdu->CRC = MB_PP_HTONS(crc);
    *pDstLen = 5;
    return MB_OK;
}

/**
 * @brief 判断接数据帧的长度
 * @param pReqADU   指针,输入数据
 * @ret pDstLen 数据长度
*/
uint16_t MB_SLAVE_GetPacketLength(uint8_t *pSrc)
{
    uint16_t packetLength = 8;
    MB_ADU_HandleTypeDef *pReqADU = (MB_ADU_HandleTypeDef *)pSrc;

    if ((pReqADU->Pdu.FunctionCode == MB_FUN_WRITE_MULTIPLE_COILS) || (pReqADU->Pdu.FunctionCode == MB_FUN_WRITE_MULTIPLE_REGISTERS))
    {
        //01 0F 00 00 00 00 XX ......
        packetLength = ((pReqADU->Pdu.Data[4]) + 9);
    }

    if (pReqADU->Pdu.FunctionCode == MB_FUN_READ_WRITE_MULTIPLE_REGISTERS)
    {
        packetLength = ((pReqADU->Pdu.Data[8]) + 13);
    }
    return packetLength;
}

/**
 * @brief 从站协议入口
 * @param hslave 从站指针
 * @param pSrc   输入数据
 * @param pDst   回复数据
 * @param pDstLen 回复数据长度
 * @ret   MB_OK  正确, MB_ERROR 失败
*/
MB_StatusTypeDef MB_SLAVE_PraseReq(MB_SLAVE_HandleTypeDef *hslave, uint8_t *pSrc, uint8_t *pDst, uint16_t *pDstLen)
{
    uint16_t packetLen = 0;
    uint32_t crcCheck = 0;
    MB_ADU_HandleTypeDef *pReqADU = (MB_ADU_HandleTypeDef *)pSrc;

    MB_ASSERT(hslave);
    MB_ASSERT(pSrc);
    MB_ASSERT(pDst);
    MB_ASSERT(pDstLen);
    //地址校验
    if (hslave->SlaveID == pReqADU->AdditionalAddress)
    {
        //CRC16校验
        packetLen = MB_SLAVE_GetPacketLength(pSrc);

        if (packetLen > 0 && packetLen < MB_MAX_PDU_DATA_LEN + 4)
        {
            crcCheck = MB_CheckRTUMessageIntegrity(pSrc, packetLen);
        }

        if (crcCheck)
        {
            //报文解析
            switch (pReqADU->Pdu.FunctionCode)
            {
            case MB_FUN_READ_COILS: // 1
                MB_LOG(MB_SLAVE, "MB_FUN_READ_COILS \n");
                return MB_COILS_Read_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_READ_DISCRETE_INPUTS: // 2
                MB_LOG(MB_SLAVE, "MB_DISINPUT_Read_Response \n");
                return MB_DISINPUT_Read_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_READ_HOLDING_REGISTERS: // 3
                MB_LOG(MB_SLAVE, "MB_HOLDREG_Read_Response \n");
                return MB_HOLDREG_Read_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_READ_INPUT_REGISTER: // 4
                MB_LOG(MB_SLAVE, "MB_INPUTREG_Read_Response \n");
                return MB_INPUTREG_Read_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_WRITE_SINGLE_COILS: // 5
                MB_LOG(MB_SLAVE, "MB_COILS_WriteSingle_Response \n");
                return MB_COILS_WriteSingle_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_WRITE_SINGLE_REGISTER: // 6
                MB_LOG(MB_SLAVE, "MB_HOLDREG_WriteSingle_Response \n");
                return MB_HOLDREG_WriteSingle_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_WRITE_MULTIPLE_COILS: // 15
                MB_LOG(MB_SLAVE, "MB_COILS_WriteMultiple_Response \n");
                return MB_COILS_WriteMultiple_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_WRITE_MULTIPLE_REGISTERS: // 16
                MB_LOG(MB_SLAVE, "MB_HOLDREG_WriteMultiple_Response \n");
                return MB_HOLDREG_WriteMultiple_Response(hslave, pSrc, pDst, pDstLen);
            case MB_FUN_READ_WRITE_MULTIPLE_REGISTERS: // 23
                MB_LOG(MB_SLAVE, "MB_HOLDREG_ReadWriteMultiple_Response \n");
                return MB_HOLDREG_ReadWriteMultiple_Response(hslave, pSrc, pDst, pDstLen);
                break;
            default:
                return MB_ERROR;
            }
        }
        MB_LOG(MB_SLAVE, "MB_SLAVE_CRC_CHECK_FAILED! \n");
        return MB_ERROR;
    }
    else
    {
        return MB_ERROR;
    }
}

/**
 * @brief 从站初始化
 * @param hslave 从站指针
 * @ret   void
*/
void MBS_Slave_init(MB_SLAVE_HandleTypeDef *hslave, uint32_t SlaveID)
{
    hslave->SlaveID = SlaveID;
}
